﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Amazon.IdentityManagement.Model;
using AmazonGlacierGUI.Core.Helpers.AmazonGlacier;
using AmazonGlacierGUI.Core.Infrastructure;
using AmazonGlacierGUI.Core.Model;
using Raven.Client;

namespace AmazonGlacierGUI.Core.Services
{
    public class AppService
    {
        private IDocumentSession _session;
        public AppService(IDocumentSession session)
        {
            _session = session;
        }
        VaultDetails GetVaultById(Guid id)
        {
            return _session.Query<VaultDetails>().Where(p => p.Id == id).FirstOrDefault();
        }

        public void SaveAppSettings()
        {
            _session.Store(AppContext.Current.Settings);
            _session.SaveChanges();
        }
        public void SaveAppSettings(AppSettings settings)
        {
            _session.Store(settings);
            _session.SaveChanges();
            AppContext.Current.Settings = settings;
        }
        public AppSettings GetAppSettings()
        {
            return _session.Query<AppSettings>().FirstOrDefault();
        }
        public void SaveJob(JobDescription job)
        {
            _session.Store(job);
            _session.SaveChanges();
        }
        public void SaveHistory(UploadHistory history)
        {
            _session.Store(history);
            _session.SaveChanges();
        }
        public List<JobDescription> GetJobs()
        {
            return _session.Query<JobDescription>().ToList();
        }
        public JobDescription GetJobById(Guid id)
        {
            return _session.Query<JobDescription>().Where(p => p.Id == id).FirstOrDefault();
        }
        public void RemoveJob(Guid id)
        {
            var s = GetJobById(id);
            if (s == null) return;
            _session.Delete(s);
            _session.SaveChanges();
        }
        public List<UploadHistory> GetUploadHistory()
        {
            return _session.Query<UploadHistory>().ToList();
        }
        public List<VaultDetails> GetVaultDetailsByRegion(AmazonRegionEnum region, bool reload)
        {
            var currentVaults = _session.Query<VaultDetails>().Where(p => p.Region == region).ToList();
            if (reload || currentVaults.Count == 0)
            {
                _session.SaveChanges();
                var helper = new AmazonGlacierHelper();
                var res = new List<VaultDetails>();
                helper.Region = region;
                SetupHelper(helper);
                var vaults = helper.GetVaults(region);
                //delete vaults that don't exist
                foreach (var currentVault in currentVaults)
                {
                    if (!vaults.Any(p => p.VaultName == currentVault.VaultName))
                    {
                        _session.Delete(currentVault);
                    }
                }
                foreach (var vault in vaults)
                {
                    var currentVault =
                        _session.Query<VaultDetails>().Where(p => p.VaultName == vault.VaultName).FirstOrDefault();
                    //if exist update else add
                    if (currentVault == null)
                    {
                        _session.Store(vault);
                        res.Add(vault);
                    }
                    else
                    {
                        currentVault.TotalSize = vault.TotalSize;
                        currentVault.NumberOfArchives = vault.NumberOfArchives;
                        currentVault.VaultName = vault.VaultName;
                        res.Add(currentVault);
                    }
                }
                _session.SaveChanges();
                return res;
            }
            return currentVaults;
        }

        public List<UploadHistory> GetUploadHistory(AmazonRegionEnum region, string vaultName)
        {
            return _session.Query<UploadHistory>().Where(p => p.Region == region && p.VaultName == vaultName).ToList();
        }
        public void ResetInventoryRequest(Guid vaultId)
        {
            var vault = GetVaultById(vaultId);
            vault.IsInventoryRequested = false;
            _session.SaveChanges();

        }
        public void RequestInventory(Guid vaultId)
        {
            var vault = GetVaultById(vaultId);
            var helper = new AmazonGlacierHelper();
            SetupHelper(helper, vault);
            vault.InventoryJobId = helper.RequestInventory();
            vault.IsInventoryRequested = true;
            vault.InventoryRequestedOn = AppUtility.GetDate();
            _session.SaveChanges();

        }
        public VaultInventory GetCachedInventory(Guid vaultId)
        {
            var vault = GetVaultById(vaultId);
            return _session.Query<VaultInventory>().Where(p => p.VaultARN == vault.VaultARN).FirstOrDefault();
        }
        public VaultInventory GetInventory(Guid vaultId)
        {
            var vault = GetVaultById(vaultId);
            var helper = new AmazonGlacierHelper();
            SetupHelper(helper, vault);
            var jobStatus = helper.GetJobStatus(vault.InventoryJobId);
            if (!jobStatus.IsCompleted) return null;
            var inventory = helper.GetVaultInventory(vault.InventoryJobId);
            var curInventory =
                _session.Query<VaultInventory>().Where(p => p.VaultARN == vault.VaultARN).FirstOrDefault();
            if (curInventory != null)
            {
                _session.Delete(curInventory);
            }
            vault.LastInventoryOn = inventory.InventoryDate;
            vault.IsInventoryRequested = false;
            _session.Store(inventory);
            _session.SaveChanges();
            return inventory;
        }
        public void DeleteArchives(Guid vaultId, string[] archiveIds)
        {
            var vault = GetVaultById(vaultId);
            var helper = new AmazonGlacierHelper();
            SetupHelper(helper, vault);
            var inventory = _session.Query<VaultInventory>().Where(p => p.VaultARN == vault.VaultARN).FirstOrDefault();
            var histories = _session.Query<UploadHistory>().Where(p => p.VaultName == vault.VaultName).ToList();
            try
            {
                foreach (var archiveId in archiveIds)
                {
                    helper.DeleteArchive(archiveId);
                    if(inventory!=null)
                    {
                        var archive = inventory.ArchiveDetails.Where(p => p.ArchiveId == archiveId).First();
                        inventory.ArchiveDetails.Remove(archive);
                    }
                    var uh = histories.Where(p => p.ArchiveId == archiveId).FirstOrDefault();
                    if(uh!=null)
                    {
                        _session.Delete(uh);
                    }
                }
            }
            finally
            {                
                _session.SaveChanges();
            }

        }

        void SetupHelper(AmazonGlacierHelperBase helper)
        {
            helper.AccessKey = AppContext.Current.Settings.AccessKey;
            helper.SecretAccessKey = AppContext.Current.Settings.SecretAccessKey;

        }
        void SetupHelper(AmazonGlacierHelperBase helper, VaultDetails vault)
        {
            helper.AccessKey = AppContext.Current.Settings.AccessKey;
            helper.SecretAccessKey = AppContext.Current.Settings.SecretAccessKey;
            helper.VaultName = vault.VaultName;
            helper.Region = vault.Region;
        }
    }
}
